home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '87 / Source ƒ.sea / Source ƒ / emacs source ƒ / TERMIO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-28  |  12.5 KB  |  459 lines  |  [TEXT/MARC]

  1. /*
  2.  * The functions in this file negotiate with the operating system for
  3.  * characters, and write characters in a barely buffered fashion on the display.
  4.  * All operating systems.
  5.  */
  6. #include        <stdio.h>
  7. #include    "estruct.h"
  8. #include        "edef.h"
  9.  
  10. #if     AMIGA
  11. #define NEW 1006
  12. #define AMG_MAXBUF      1024L
  13. static long terminal;
  14. static char     scrn_tmp[AMG_MAXBUF+1];
  15. static long     scrn_tmp_p = 0;
  16. #endif
  17.  
  18. #if     VMS
  19. #include        <stsdef.h>
  20. #include        <ssdef.h>
  21. #include        <descrip.h>
  22. #include        <iodef.h>
  23. #include        <ttdef.h>
  24. #include    <tt2def.h>
  25.  
  26. #define NIBUF   128                     /* Input buffer size            */
  27. #define NOBUF   1024                    /* MM says bug buffers win!     */
  28. #define EFN     0                       /* Event flag                   */
  29.  
  30. char    obuf[NOBUF];                    /* Output buffer                */
  31. int     nobuf;                  /* # of bytes in above    */
  32. char    ibuf[NIBUF];                    /* Input buffer          */
  33. int     nibuf;                  /* # of bytes in above  */
  34. int     ibufi;                  /* Read index                   */
  35. int     oldmode[3];                     /* Old TTY mode bits            */
  36. int     newmode[3];                     /* New TTY mode bits            */
  37. short   iochan;                  /* TTY I/O channel             */
  38. #endif
  39.  
  40. #if     CPM
  41. #include        <bdos.h>
  42. #endif
  43.  
  44. #if     MSDOS & (LATTICE | MSC | AZTEC)
  45. union REGS rg;        /* cpu register for use of DOS calls */
  46. int nxtchar = -1;    /* character held from type ahead    */
  47. #endif
  48.  
  49. #if RAINBOW
  50. #include "rainbow.h"
  51. #endif
  52.  
  53. #if    USG            /* System V */
  54. #include    <signal.h>
  55. #include    <termio.h>
  56. struct    termio    otermio;    /* original terminal characteristics */
  57. struct    termio    ntermio;    /* charactoristics to use inside */
  58. #endif
  59.  
  60. #if V7 | BSD
  61. #undef    CTRL
  62. #include        <sgtty.h>        /* for stty/gtty functions */
  63. #include    <signal.h>
  64. struct  sgttyb  ostate;          /* saved tty state */
  65. struct  sgttyb  nstate;          /* values for editor mode */
  66. struct tchars    otchars;    /* Saved terminal special character set */
  67. struct tchars    ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  68.                 /* A lot of nothing */
  69. #if BSD
  70. #include <sys/ioctl.h>        /* to get at the typeahead */
  71. extern    int rtfrmshell();    /* return from suspended shell */
  72. #define    TBUFSIZ    128
  73. char tobuf[TBUFSIZ];        /* terminal output buffer */
  74. #endif
  75. #endif
  76.  
  77. /*
  78.  * This function is called once to set up the terminal device streams.
  79.  * On VMS, it translates TT until it finds the terminal, then assigns
  80.  * a channel to it and sets it raw. On CPM it is a no-op.
  81.  */
  82. ttopen()
  83. {
  84. #if     AMIGA
  85.         terminal = Open("RAW:1/1/639/199/MicroEMACS 3.7/Amiga", NEW);
  86. #endif
  87. #if     VMS
  88.         struct  dsc$descriptor  idsc;
  89.         struct  dsc$descriptor  odsc;
  90.         char    oname[40];
  91.         int     iosb[2];
  92.         int     status;
  93.  
  94.         odsc.dsc$a_pointer = "TT";
  95.         odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
  96.         odsc.dsc$b_dtype        = DSC$K_DTYPE_T;
  97.         odsc.dsc$b_class        = DSC$K_CLASS_S;
  98.         idsc.dsc$b_dtype        = DSC$K_DTYPE_T;
  99.         idsc.dsc$b_class        = DSC$K_CLASS_S;
  100.         do {
  101.                 idsc.dsc$a_pointer = odsc.dsc$a_pointer;
  102.                 idsc.dsc$w_length  = odsc.dsc$w_length;
  103.                 odsc.dsc$a_pointer = &oname[0];
  104.                 odsc.dsc$w_length  = sizeof(oname);
  105.                 status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
  106.                 if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
  107.                         exit(status);
  108.                 if (oname[0] == 0x1B) {
  109.                         odsc.dsc$a_pointer += 4;
  110.                         odsc.dsc$w_length  -= 4;
  111.                 }
  112.         } while (status == SS$_NORMAL);
  113.         status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
  114.         if (status != SS$_NORMAL)
  115.                 exit(status);
  116.         status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
  117.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  118.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  119.                 exit(status);
  120.         newmode[0] = oldmode[0];
  121.         newmode[1] = oldmode[1] | TT$M_NOECHO;
  122.         newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
  123.         newmode[2] = oldmode[2] | TT2$M_PASTHRU;
  124.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  125.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  126.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  127.                 exit(status);
  128.         term.t_nrow = (newmode[1]>>24) - 1;
  129.         term.t_ncol = newmode[0]>>16;
  130.  
  131. #endif
  132. #if     CPM
  133. #endif
  134.  
  135. #if     MSDOS & (HP150 == 0) & LATTICE
  136.     /* kill the ctrl-break interupt */
  137.     rg.h.ah = 0x33;        /* control-break check dos call */
  138.     rg.h.al = 1;        /* set the current state */
  139.     rg.h.dl = 0;        /* set it OFF */
  140.     intdos(&rg, &rg);    /* go for it! */
  141. #endif
  142.  
  143. #if    USG
  144.     ioctl(0, TCGETA, &otermio);    /* save old settings */
  145.     ntermio.c_iflag = 0;        /* setup new settings */
  146.     ntermio.c_oflag = 0;
  147.     ntermio.c_cflag = otermio.c_cflag;
  148.     ntermio.c_lflag = 0;
  149.     ntermio.c_line = otermio.c_line;
  150.     ntermio.c_cc[VMIN] = 1;
  151.     ntermio.c_cc[VTIME] = 0;
  152.     ioctl(0, TCSETA, &ntermio);    /* and activate them */
  153. #endif
  154.  
  155. #if     V7 | BSD
  156.         gtty(0, &ostate);                       /* save old state */
  157.         gtty(0, &nstate);                       /* get base of new state */
  158.         nstate.sg_flags |= RAW;
  159.         nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
  160.         stty(0, &nstate);                       /* set mode */
  161.     ioctl(0, TIOCGETC, &otchars);        /* Save old characters */
  162.     ioctl(0, TIOCSETC, &ntchars);        /* Place new character into K */
  163. #if    BSD
  164.     /* provide a smaller terminal output buffer so that
  165.        the type ahead detection works better (more often) */
  166.     setbuffer(stdout, &tobuf[0], TBUFSIZ);
  167.     signal(SIGTSTP,SIG_DFL);    /* set signals so that we can */
  168.     signal(SIGCONT,rtfrmshell);    /* suspend & restart emacs */
  169. #endif
  170. #endif
  171.     /* on all screens we are not sure of the initial position
  172.        of the cursor                    */
  173.     ttrow = 999;
  174.     ttcol = 999;
  175. }
  176.  
  177. /*
  178.  * This function gets called just before we go back home to the command
  179.  * interpreter. On VMS it puts the terminal back in a reasonable state.
  180.  * Another no-operation on CPM.
  181.  */
  182. ttclose()
  183. {
  184. #if     AMIGA
  185.         amg_flush();
  186.         Close(terminal);
  187. #endif
  188. #if     VMS
  189.         int     status;
  190.         int     iosb[1];
  191.  
  192.         ttflush();
  193.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  194.                  oldmode, sizeof(oldmode), 0, 0, 0, 0);
  195.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  196.                 exit(status);
  197.         status = SYS$DASSGN(iochan);
  198.         if (status != SS$_NORMAL)
  199.                 exit(status);
  200. #endif
  201. #if     CPM
  202. #endif
  203. #if     MSDOS & (HP150 == 0) & LATTICE
  204.     /* restore the ctrl-break interupt */
  205.     rg.h.ah = 0x33;        /* control-break check dos call */
  206.     rg.h.al = 1;        /* set the current state */
  207.     rg.h.dl = 1;        /* set it ON */
  208.     intdos(&rg, &rg);    /* go for it! */
  209. #endif
  210.  
  211. #if    USG
  212.     ioctl(0, TCSETA, &otermio);    /* restore terminal settings */
  213. #endif
  214.  
  215. #if     V7 | BSD
  216.         stty(0, &ostate);
  217.     ioctl(0, TIOCSETC, &otchars);    /* Place old character into K */
  218. #endif
  219. }
  220.  
  221. /*
  222.  * Write a character to the display. On VMS, terminal output is buffered, and
  223.  * we just put the characters in the big array, after checking for overflow.
  224.  * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
  225.  * MS-DOS (use the very very raw console output routine).
  226.  */
  227. ttputc(c)
  228. #if     AMIGA
  229.         char c;
  230. #endif
  231. {
  232. #if     AMIGA
  233.         scrn_tmp[scrn_tmp_p++] = c;
  234.         if(scrn_tmp_p>=AMG_MAXBUF)
  235.                 amg_flush();
  236. #endif
  237. #if     VMS
  238.         if (nobuf >= NOBUF)
  239.                 ttflush();
  240.         obuf[nobuf++] = c;
  241. #endif
  242.  
  243. #if     CPM
  244.         bios(BCONOUT, c, 0);
  245. #endif
  246.  
  247. #if     MSDOS & MWC86
  248.         dosb(CONDIO, c, 0);
  249. #endif
  250.  
  251. #if    MSDOS & (LATTICE | AZTEC) & ~IBMPC
  252.     bdos(6, c, 0);
  253. #endif
  254.  
  255. #if RAINBOW
  256.         Put_Char(c);                    /* fast video */
  257. #endif
  258.  
  259.  
  260. #if     V7 | USG | BSD
  261.         fputc(c, stdout);
  262. #endif
  263. }
  264.  
  265. #if    AMIGA
  266. amg_flush()
  267. {
  268.         if(scrn_tmp_p)
  269.                 Write(terminal,scrn_tmp,scrn_tmp_p);
  270.         scrn_tmp_p = 0;
  271. }
  272. #endif
  273.  
  274. /*
  275.  * Flush terminal buffer. Does real work where the terminal output is buffered
  276.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  277.  */
  278. ttflush()
  279. {
  280. #if     AMIGA
  281.         amg_flush();
  282. #endif
  283. #if     VMS
  284.         int     status;
  285.         int     iosb[2];
  286.  
  287.         status = SS$_NORMAL;
  288.         if (nobuf != 0) {
  289.                 status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
  290.                          iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
  291.                 if (status == SS$_NORMAL)
  292.                         status = iosb[0] & 0xFFFF;
  293.                 nobuf = 0;
  294.         }
  295.         return (status);
  296. #endif
  297.  
  298. #if     CPM
  299. #endif
  300.  
  301. #if     MSDOS
  302. #endif
  303.  
  304. #if     V7 | USG | BSD
  305.         fflush(stdout);
  306. #endif
  307. }
  308.  
  309. /*
  310.  * Read a character from the terminal, performing no editing and doing no echo
  311.  * at all. More complex in VMS that almost anyplace else, which figures. Very
  312.  * simple on CPM, because the system can do exactly what you want.
  313.  */
  314. ttgetc()
  315. {
  316. #if     AMIGA
  317.         char ch;
  318.         amg_flush();
  319.         Read(terminal, &ch, 1L);
  320.         return(255 & (int)ch);
  321. #endif
  322. #if     VMS
  323.         int     status;
  324.         int     iosb[2];
  325.         int     term[2];
  326.  
  327.         while (ibufi >= nibuf) {
  328.                 ibufi = 0;
  329.                 term[0] = 0;
  330.                 term[1] = 0;
  331.                 status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
  332.                          iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
  333.                 if (status != SS$_NORMAL)
  334.                         exit(status);
  335.                 status = iosb[0] & 0xFFFF;
  336.                 if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
  337.                         exit(status);
  338.                 nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  339.                 if (nibuf == 0) {
  340.                         status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
  341.                                  iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
  342.                         if (status != SS$_NORMAL
  343.                         || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
  344.                                 exit(status);
  345.                         nibuf = (iosb[0]>>16) + (iosb[1]>>16);
  346.                 }
  347.         }
  348.         return (ibuf[ibufi++] & 0xFF);    /* Allow multinational  */
  349. #endif
  350.  
  351. #if     CPM
  352.         return (biosb(BCONIN, 0, 0));
  353. #endif
  354.  
  355. #if RAINBOW
  356.         int Ch;
  357.  
  358.         while ((Ch = Read_Keyboard()) < 0);
  359.  
  360.         if ((Ch & Function_Key) == 0)
  361.                 if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
  362.                         Ch &= 0xFF;
  363.  
  364.         return Ch;
  365. #endif
  366.  
  367. #if     MSDOS & MWC86
  368.         return (dosb(CONRAW, 0, 0));
  369. #endif
  370.  
  371. #if    MSDOS & (LATTICE | MSC)
  372.     int c;        /* character read */
  373.  
  374.     /* if a char already is ready, return it */
  375.     if (nxtchar >= 0) {
  376.         c = nxtchar;
  377.         nxtchar = -1;
  378.         return(c);
  379.     }
  380.  
  381.     /* call the dos to get a char */
  382.     rg.h.ah = 7;        /* dos Direct Console Input call */
  383.     intdos(&rg, &rg);
  384.     c = rg.h.al;        /* grab the char */
  385.     return(c & 255);
  386. #endif
  387.  
  388. #if    MSDOS & AZTEC
  389.     int c;        /* character read */
  390.  
  391.     /* if a char already is ready, return it */
  392.     if (nxtchar >= 0) {
  393.         c = nxtchar;
  394.         nxtchar = -1;
  395.         return(c);
  396.     }
  397.  
  398.     /* call the dos to get a char */
  399.     rg.h.ah = 7;        /* dos Direct Console I/O call */
  400.     sysint(33, &rg, &rg);
  401.     c = rg.h.al;        /* grab the char */
  402.     return(c & 255);
  403. #endif
  404.  
  405. #if     V7 | USG | BSD
  406.         return(127 & fgetc(stdin));
  407. #endif
  408. }
  409.  
  410. #if    TYPEAH
  411. /* typahead:    Check to see if any characters are already in the
  412.         keyboard buffer
  413. */
  414.  
  415. typahead()
  416.  
  417. {
  418. #if    MSDOS & (LATTICE | AZTEC)
  419.     int c;        /* character read */
  420.     int flags;    /* cpu flags from dos call */
  421.  
  422. #if    MSC
  423.     if (kbhit() != 0)
  424.         return(TRUE);
  425.     else
  426.         return(FALSE);
  427. #endif
  428.  
  429.     if (nxtchar >= 0)
  430.         return(TRUE);
  431.  
  432.     rg.h.ah = 6;    /* Direct Console I/O call */
  433.     rg.h.dl = 255;    /*         does console input */
  434. #if    LATTICE
  435.     flags = intdos(&rg, &rg);
  436. #else
  437.     flags = sysint(33, &rg, &rg);
  438. #endif
  439.     c = rg.h.al;    /* grab the character */
  440.  
  441.     /* no character pending */
  442.     if ((flags & 64) != 0)
  443.         return(FALSE);
  444.  
  445.     /* save the character and return true */
  446.     nxtchar = c;
  447.     return(TRUE);
  448. #endif
  449.  
  450. #if    BSD
  451.     int x;    /* holds # of pending chars */
  452.  
  453.     return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
  454. #endif
  455.     return(FALSE);
  456. }
  457. #endif
  458.  
  459.